package com.yxw.live_vod_backend_boot.log;

import com.yxw.live_vod_backend_boot.entity.SysOptLogEntity;
import com.yxw.live_vod_backend_boot.service.LogService;
import com.yxw.live_vod_backend_boot.util.UserUtil;
import com.yxw.yxnet_cd_center.common.constant.CommonConstant;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.util.Arrays;

/**
 * 操作日志切面
 * liuxin
 * 2023.10.27
 */
@Aspect
@Component
@Slf4j
public class OptLogAspect {

    @Autowired
    private LogService logService;

    @Autowired
    private UserUtil userUtil;

    // 定义ThreadLocal，用于保存请求信息
    private ThreadLocal<SysOptLogEntity> optLogThreadLocal = new ThreadLocal<>();

    /**
     * 切入方法入口路径
     */
    @Pointcut(value = "execution(* com.yxw.live_vod_backend_boot.controller.*.*(..))")
    public void inletPointcut() {

    }

    /**
     * 切入方法出口路径
     */
    @Pointcut(value = "execution(* com.yxw.live_vod_backend_boot.exception.*.*(..))")
    public void exceptionPointcut() {

    }

    //进入切入方法前执行
    @Before("inletPointcut()")
    public void before(JoinPoint joinPoint) {
        try {
            SysOptLogEntity optLog = new SysOptLogEntity();
            optLog.setIpAddress(((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest().getRemoteAddr());
            optLog.setUrl(((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest().getRequestURI());
            optLog.setPathMethod(((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest().getMethod());
            optLog.setRequestParam(Arrays.toString(joinPoint.getArgs()));
            optLog.setUserId(userUtil.getLoginUserId());
            optLog.setUserName(userUtil.getLoginName());
            optLogThreadLocal.set(optLog);
        }catch (Exception e){
            log.error("入口切面出错{}",e.getMessage());
        }
    }

    //进入切入方法前执行
    @AfterReturning(returning  = "result",pointcut = "inletPointcut()")
    public void AfterReturning(JoinPoint joinPoint,Object result) {
        try {
            SysOptLogEntity optLog = optLogThreadLocal.get();
            optLog.setResponseParam(result.toString());
            optLog.setStatus(CommonConstant.ONE);
            optLogThreadLocal.remove();
            logService.addOptLog(optLog);
            }catch (Exception e){
            log.error("出口切面出错{}",e.getMessage());
        }
    }

    /**
     * 切口方法异常处理
     */
    @AfterThrowing(value = "exceptionPointcut()",throwing = "e")
    public void afterThrowing(Throwable e){
        try {
            SysOptLogEntity optLog = optLogThreadLocal.get();
            optLog.setResponseParam(e.getMessage());
            optLog.setStatus(CommonConstant.ZERO);
            optLogThreadLocal.remove();
            logService.addOptLog(optLog);
        }catch (Exception ee){
            log.error("出口切面出错{}",ee.getMessage());
        }
    }

}